package com.lolaage.tsr.dals.base;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterDisposer;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.RowMapperResultSetExtractor;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.util.Assert;

import com.lolaage.tsr.dals.common.EntityResult;
import com.lolaage.tsr.dals.common.GeneratorType;
import com.lolaage.tsr.dals.common.PageBean;
import com.lolaage.tsr.dals.common.Transient;
import com.lolaage.tsr.dals.util.ContextUtil;
import com.lolaage.tsr.dals.util.EmojiFilterUtil;

/**
 * @author 邓鹏
 * @Project
 * @Date 2012-12-22
 * @ReMarks
 */
public class SpringDaoImpl extends JdbcTemplate implements IBaseDao {
	protected Logger log = Logger.getLogger(SpringDaoImpl.class);

	protected String tablePrefix;
	/** 是否过滤emoji表情 */
	private boolean isFilterEmoji = false;

	public SpringDaoImpl() {
		try {
			tablePrefix = ContextUtil.getInitConfig("table.prefix");
			isFilterEmoji = Boolean.parseBoolean(ContextUtil.getInitConfig("isfilteremoji"));
		} catch (Exception e) {
			tablePrefix = "";
			isFilterEmoji = false;
			e.printStackTrace();
		}
	}

	protected String getTablePrefix() {
		return tablePrefix;
	}

	public static final String IS_SET_NULL_VALUE = "isSetNullValue";

	protected String getFieldPrefix() {
		return "";
	}

	public void delete(Object entity) {
		String idColumnName = getIdColumnNameByEntity(entity);
		String _tableName = getTableName(entity.getClass());
		String sql = "delete from " + _tableName + " where " + getFieldPrefix() + idColumnName + "=?";
		try {
			Method getMethod = entity.getClass().getDeclaredMethod(getGetterName(idColumnName), null);
			Object idValue = getMethod.invoke(entity, null);
			this.update(sql, new Object[] { idValue });
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 根据IDS批量删除数据。 IDS是以英文逗号分隔的ID字符串。
	 * 
	 * @param clazz
	 * @param ids
	 */
	public void deleteByIds(Class clazz, String ids) {
		String idColumnName = getIdColumnNameByClass(clazz, null);
		String _tableName = getTableName(clazz);
		String sql = "delete from " + _tableName + " where " + getFieldPrefix() + idColumnName + "=?";
		String idsArray[] = ids.split(",");
		for (int i = 0; i < idsArray.length; i++) {
			this.update(sql, new Object[] { idsArray[i] });
		}
	}

	protected String getIdColumnNameByClass(Class entityClass, Object entity) {
		Method mehtod = null;
		try {
			mehtod = entityClass.getDeclaredMethod("getIdColumnName", null);
		} catch (Exception e) {
			try {
				mehtod = entityClass.getSuperclass().getDeclaredMethod("getIdColumnName", null);
			} catch (Exception e1) {
				throw new RuntimeException("要使用本类的函数来操作数据库，实体类：[" + entityClass.getName() + "]，中必须包含getIdColumnName方法，建议继承BaseEntity！");
			}
		}

		try {
			Object newEntity = null;
			if (entity != null)
				newEntity = entity;
			else
				newEntity = entityClass.newInstance();
			return (String) mehtod.invoke(newEntity, null);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获取实体ID列名的方法。
	 * 
	 * @param entity
	 * @return
	 */
	protected String getIdColumnNameByEntity(Object entity) {
		return getIdColumnNameByClass(entity.getClass(), entity);
	}

	/**
	 * 获取表名的方法。
	 * 
	 * @param arg
	 * @return
	 */
	public String getTableName(Class entityClass) {
		String arg = entityClass.getSimpleName();

		StringBuffer result = new StringBuffer(tablePrefix);

		for (int i = 0; i < arg.length(); i++) {
			String s = arg.charAt(i) + "";
			String pattern = "[A-Z]";
			boolean flag;
			if (i == 0) {
				flag = s.matches(pattern) && !(arg.charAt(i + 1) + "").matches(pattern);
			} else if (i + 1 < arg.length()) {
				flag = s.matches(pattern) && !(arg.charAt(i - 1) + "").matches(pattern) && !(arg.charAt(i + 1) + "").matches(pattern);
			} else {
				flag = s.matches(pattern) && !(arg.charAt(i - 1) + "").matches(pattern);
			}
			if (flag) {
				if (i == 0)
					result.append(s.toLowerCase());
				else
					result.append("_" + s.toLowerCase());
			} else {
				result.append(s);
			}
		}
		return result.toString();
	}

	/**
	 * 批量执行SQL语句。
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public int[] batchExecuteSql(String sql, final Object[][] params) {
		if (params == null || params.length == 0)
			return new int[0];
		int[] result = this.batchUpdate(sql, new BatchPreparedStatementSetter() {
			public int getBatchSize() {
				return params.length;
			}

			public void setValues(PreparedStatement ps, int index) throws SQLException {
				Object[] param = params[index];
				for (int i = 0; i < param.length; i++) {
					Object oneParam = param[i];
					ps.setObject(i + 1, oneParam);
				}
			}
		});

		return result;
	}

	/**
	 * 获取实体有值的所有字段MAP，包含字段列表和值列表(不包括ID)
	 * 
	 * @param entity
	 * @return
	 */
	protected EntityResult getEntityValueMap(Object entity) {
		return getEntityValueMap(entity, null);
	}

	/**
	 * 获取实体有值的所有字段MAP，包含字段列表和值列表(不包括ID)
	 * 
	 * @param entity
	 * @param likeFieldList
	 * @param setIdValue
	 *            是否在IDColumn为空时自动生成ID值
	 * @return
	 */
	protected EntityResult getEntityValueMap(Object entity, List<String> likeFieldList) {
		EntityResult entityResult = new EntityResult();
		Map<String, Object> map = new HashMap<String, Object>();
		List<String> fieldList = new ArrayList<String>();
		Map<String, Object> valueMap = new HashMap<String, Object>();
		List<Field> fields = new ArrayList<Field>();
		fields.addAll(Arrays.asList(entity.getClass().getDeclaredFields()));
		for (Field f : fields) {

			// 如果是静态或者final字段，则跳过。
			if (Modifier.isStatic(f.getModifiers()) || Modifier.isFinal(f.getModifiers()))
				continue;

			if (!isBaseType(f.getType()))
				continue;
			if (getIdColumnNameByEntity(entity).equalsIgnoreCase(f.getName())) {
				entityResult.setGeneratorType(GeneratorType.IDENTITY);
				// Generator generator = f.getAnnotation(Generator.class);
				// if(generator !=
				// null&&generator.value()==GeneratorType.IDENTITY){
				// entityResult.setGeneratorType(GeneratorType.IDENTITY);
				// }else{
				// if (isFieldValueNull(entity, f.getName())) {
				// fieldList.add(getFieldPrefix()+f.getName());
				// Long id =
				// RouteDBFactory.getInstance().getId(getTableName(entity.getClass()));
				// valueMap.put(f.getName(), id);
				// setIdentityValue(entity, id);
				// continue ;
				// } else {
				// fieldList.add(getFieldPrefix()+f.getName());
				// valueMap.put(f.getName(), getIdentityValue(entity));
				// continue ;
				// }
				// }
				continue;
			}

			Transient ta = f.getAnnotation(Transient.class);
			if (ta != null)
				continue;

			f.setAccessible(true);
			Object value = null;
			try {
				value = f.get(entity);
				if (value instanceof String && isFilterEmoji && value != null && !"".equals(value.toString())) {
					value = EmojiFilterUtil.filterEmoji(value.toString());
				}
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
			if (value == null || "".equals(value.toString()))
				continue;
			fieldList.add(getFieldPrefix() + f.getName());
			if (IS_SET_NULL_VALUE.equals(value.toString().trim()))
				continue;
			if (likeFieldList != null && likeFieldList.contains(f.getName())) {
				valueMap.put(getFieldPrefix() + f.getName(), "%" + value + "%");
			} else {
				valueMap.put(getFieldPrefix() + f.getName(), value);
			}
		}
		map.put("fieldList", fieldList);
		// map.put("valueList", valueList);
		map.put("valueMap", valueMap);
		entityResult.setEntityMap(map);
		return entityResult;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Long save(Object entity) {
		EntityResult entityResult = getEntityValueMap(entity, null);
		Map<String, Object> map = entityResult.getEntityMap();
		GeneratorType generatorType = entityResult.getGeneratorType();
		List<String> fieldList = (List<String>) map.get("fieldList");
		List<Object> valueList = new ArrayList<Object>();
		// valueList.addAll((List<Object>) map.get("valueList"));
		Map valueMap = (Map) map.get("valueMap");
		for (String oneField : fieldList) {
			String temp = oneField;
			if (oneField.startsWith("f_"))
				temp = oneField.substring(2);
			Object oneValue = valueMap.get(temp);
			if (oneValue == null)
				oneValue = valueMap.get(oneField);
			valueList.add(oneValue);
		}

		String sql = getInsertSql(entity, fieldList);
//		this.update(sql, valueList.toArray());
		 KeyHolder keyHolder = new GeneratedKeyHolder();
		 this.update(sql, valueList.toArray(), keyHolder);
//		String idColumn = getFieldPrefix() + getIdColumnNameByEntity(entity);
//		Long list = queryObjectBySql(Long.class, "select LAST_INSERT_ID()", new Object[] {});
//		return list;
		 return keyHolder.getKey().longValue();
		// if (generatorType==GeneratorType.IDENTITY) {
		// String idColumn = getFieldPrefix()+getIdColumnNameByEntity(entity);
		// List<Long> list =queryBySql(Long.class,
		// "select LAST_INSERT_ID("+idColumn+") id from "+getTableName(entity.getClass())
		// +" order by "+ idColumn+" desc limit 1", new Object[] {});
		// if (list !=null && list.size() > 0 && list.get(0) > 0) {
		// setIdentityValue(entity, Long.parseLong(list.get(0)+""));
		// return Long.parseLong(list.get(0)+"");
		// }
		// } else if(generatorType==GeneratorType.ASSIGNED){
		// return (Long) getIdentityValue(entity);
		// }
	}

	public int update(final String sql, final Object[] args, final KeyHolder generatedKeyHolder) throws DataAccessException {
		return this.update(new PreparedStatementCreator() {
			@Override
			public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
				PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
				if (args != null && args.length > 0) {
					for (int i = 1; i <= args.length; i++) {
						ps.setObject(i, args[i - 1]);
					}
				}
				return ps;
			}
		}, generatedKeyHolder);
	}

	protected String getInsertSql(Object entity, List<String> fieldList) {
		StringBuffer fieldListString = new StringBuffer("");
		StringBuffer markString = new StringBuffer("");
		for (int i = 0; i < fieldList.size(); i++) {
			fieldListString.append(fieldList.get(i)).append(",");
			markString.append("?,");
		}
		if (fieldListString.length() > 0)
			fieldListString.deleteCharAt(fieldListString.length() - 1);
		if (markString.length() > 0)
			markString.deleteCharAt(markString.length() - 1);
		String tableName = getTableName(entity.getClass());
		String sql = "insert into " + tableName + "(" + fieldListString.toString() + ") values(" + markString.toString() + ")";
		return sql;
	}

	/**
	 * 为一个Entity的ID设值。
	 * 
	 * @param entity
	 * @param id
	 * @throws DaoException
	 */
	protected String setIdentityValue(Object entity, Object id) {
		Method setMethod = null;
		String idColumnName = getIdColumnNameByEntity(entity);
		try {
			setMethod = entity.getClass().getDeclaredMethod(getSetterName(idColumnName), id.getClass());
			setMethod.invoke(entity, id);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return idColumnName;
	}

	/**
	 * 获取一个Entity的ID值。
	 * 
	 * @param entity
	 * @param id
	 * @throws DaoException
	 */
	protected Object getIdentityValue(Object entity) {
		Method getMethod = null;
		String idColumnName = getIdColumnNameByEntity(entity);
		try {
			getMethod = entity.getClass().getDeclaredMethod(getGetterName(idColumnName), null);
			return getMethod.invoke(entity, null);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	protected boolean isFieldValueNull(Object entity, String fieldName) {
		try {
			Object obj = getFieldValue(entity, fieldName);
			return obj == null || "".equals(obj.toString().trim()) ? true : false;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return true;
	}

	protected Object getFieldValue(Object entity, String fieldName) {
		try {
			Field field = entity.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			Object obj = field.get(entity);
			return obj;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	public void update(Object entity) {
		EntityResult entityResult = getEntityValueMap(entity);
		Map<String, Object> map = entityResult.getEntityMap();
		List<String> fieldList = (List<String>) map.get("fieldList");
		List<Object> valueList = new ArrayList<Object>();
		Map valueMap = (Map) map.get("valueMap");
		for (String oneField : fieldList) {
			String temp = oneField;
			if (oneField.startsWith("f_"))
				temp = oneField.substring(2);
			Object oneValue = valueMap.get(temp);
			if (oneValue == null)
				oneValue = valueMap.get(oneField);
			valueList.add(oneValue);
		}
		Object id = getIdentityValue(entity);
		try {
			valueList.add(id);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		String sql = getUpdateSql(entity, fieldList);
		this.update(sql, valueList.toArray());
	}

	protected String getUpdateSql(Object entity, List<String> fieldList) {
		StringBuffer setString = new StringBuffer("");
		for (String f : fieldList) {
			setString.append(f).append("=?,");
		}
		if (setString.length() > 0)
			setString.deleteCharAt(setString.length() - 1);
		String sql = "update " + getTableName(entity.getClass()) + " set " + setString + " where " + getFieldPrefix() + getIdColumnNameByEntity(entity) + "=?";
		return sql;
	}

	public List query(Object model) {
		return query(model, null);
	}

	protected RowMapper<Object> disposeRowMapper(final Class entityClass) {
		return new RowMapper<Object>() {
			public Object mapRow(ResultSet rs, int arg1) throws SQLException {
				try {
					Object instance = null;
					if (entityClass.equals(Map.class) || entityClass.equals(HashMap.class)) {
						Map<String, Object> map = new HashMap<String, Object>();
						ResultSetMetaData metaData = rs.getMetaData();
						for (int i = 0; i < metaData.getColumnCount(); i++) {
							String columnLabel = metaData.getColumnLabel(i + 1);
							Object value = rs.getObject(columnLabel);
							// value =
							// SensitiveMessageFilterUtil.filterContent(value);
							map.put(columnLabel, value);
						}
						return map;
					}
					Set<String> columnLabels = new HashSet<String>();// 先查询返回的字段
					ResultSetMetaData metaData = rs.getMetaData();
					for (int i = 0; i < metaData.getColumnCount(); i++) {
						String columnLabel = metaData.getColumnLabel(i + 1);
						columnLabels.add(columnLabel);
					}
					List<Field> fields = new ArrayList<Field>();
					fields.addAll(Arrays.asList(entityClass.getDeclaredFields()));
					for (Field f : fields) {
						String setterName = getSetterName(f.getName());
						String fieldName = f.getName();
						if (!columnLabels.contains(getFieldPrefix() + fieldName)) {// 比较返回的字段，如果包含才走下面
							continue;
						}
						Object value = null;
						Class<?> valueType = null;
						try {
							value = rs.getObject(getFieldPrefix() + fieldName);
							if (value == null)
								continue;
							if (instance == null) {
								instance = entityClass.newInstance();
							}
							// 目前支持的字段值类型
							if (value instanceof Integer) {
								valueType = Integer.class;
							} else if (value instanceof Long) {
								valueType = Long.class;
							} else if (value instanceof BigInteger) {
								valueType = Long.class;
							} else if (value instanceof Float) {
								valueType = Float.class;
							} else if (value instanceof Double) {
								valueType = Double.class;
							} else if (value instanceof Character) {
								valueType = Character.class;
							} else if (value instanceof Timestamp) {
								valueType = Date.class;
								value = new Date(((Timestamp) value).getTime());
							} else if (value instanceof java.sql.Date) {
								valueType = Date.class;
								value = new Date(((java.sql.Date) value).getTime());
							} else if (value instanceof BigDecimal) {
								valueType = BigDecimal.class;
							} else {
								valueType = String.class;
								// value =
								// SensitiveMessageFilterUtil.filterContent(value);
							}

							// if(entityClass.getName().equals("com.lolaage.helper.application.po.Score_helper_achieve")){
							// System.out.println(entityClass.getName());
							// }
							if (f.getType().getName().equals("java.lang.Long") && value instanceof Integer) {
								Method setter = entityClass.getDeclaredMethod(setterName, f.getType());
								try {
									setter.invoke(instance, Long.valueOf((Integer) value));
								} catch (Exception e) {
									log.error("Integer value to Long error");
								}
							} else if (f.getType().getName().equals("java.lang.Integer") && value instanceof Long) {
								Method setter = entityClass.getDeclaredMethod(setterName, f.getType());
								try {
									setter.invoke(instance, ((Long) value).intValue());
								} catch (Exception e) {
									log.error("Long value to Integer error");
								}
							} else if (f.getType().getName().equals("java.lang.Integer") && value instanceof BigDecimal) {
								Method setter = entityClass.getDeclaredMethod(setterName, f.getType());
								try {
									setter.invoke(instance, ((BigDecimal) value).intValue());
								} catch (Exception e) {
									log.error("Long value to Integer error");
								}
							} else {
								Method setter = entityClass.getDeclaredMethod(setterName, valueType);
								setter.invoke(instance, value);
							}
						} catch (Exception e) {
							try {
								if (value instanceof Timestamp) {
									valueType = Timestamp.class;
									Method setter = entityClass.getDeclaredMethod(setterName, valueType);
									setter.invoke(instance, value);
								} else if (value instanceof BigDecimal) {
									valueType = Double.class;
									value = ((BigDecimal) value).doubleValue();
									Method setter = entityClass.getDeclaredMethod(setterName, valueType);
									setter.invoke(instance, value);
								}
							} catch (Exception e1) {
								log.error(e1.getMessage(), e1);
							}
							continue;
						}
					}
					if (instance != null)
						return instance;
					try {
						return rs.getObject(1);
					} catch (SQLException e) {
						return null;
					}
				} catch (Exception e) {
					return null;
				}
			}
		};
	}

	public List query(Object model, PageBean pageBean) {
		return query(model, pageBean, null);
	}

	public List queryBySql(Class entityClass, String sql, Object[] args) {
		return queryBySql(entityClass, sql, args, null);
	}

	public List queryBySql(Class entityClass, String sql, Object[] args, PageBean pageBean) {

		List<Object> valueList = new ArrayList<Object>();
		if (args != null)
			valueList.addAll(Arrays.asList(args));
		return query(sql, null, valueList, entityClass, pageBean);
	}

	public List queryBySql(Class entityClass, String sql, String countSql, Object[] args, PageBean pageBean) {

		List<Object> valueList = new ArrayList<Object>();
		if (args != null)
			valueList.addAll(Arrays.asList(args));
		return query(sql, countSql, valueList, entityClass, pageBean);
	}

	/**
	 * 根据单个属性查询集合。
	 * 
	 * @param entityClass
	 * @param propName
	 * @param propValue
	 * @param isLike
	 *            是否采用like方式查询，如果用 = 号，则传入false.
	 * @return
	 */
	public List queryByOneProperty(Class entityClass, String propName, Object propValue, boolean isLike) {
		String tableName = getTableName(entityClass);
		String sql = "select * from " + tableName + " where " + propName;
		if (!isLike)
			sql += " = ?";
		else
			sql += " like '%?%' ";
		return this.queryBySql(entityClass, sql, new Object[] { propValue });
	}

	public List query(Object model, PageBean pageBean, String... queryByLikeFields) {
		List<String> likeFieldList = new ArrayList<String>();
		if (queryByLikeFields != null)
			likeFieldList.addAll(Arrays.asList(queryByLikeFields));
		EntityResult entityResult = getEntityValueMap(model, likeFieldList);
		Map<String, Object> map = entityResult.getEntityMap();
		List<String> fieldList = (List<String>) map.get("fieldList");
		// List<Object> list =(List<Object>) map.get("valueList");
		List<Object> list = new ArrayList<Object>();
		Map valueMap = (Map) map.get("valueMap");
		for (String oneField : fieldList) {
			String temp = oneField;
			if (oneField.startsWith("f_"))
				temp = oneField.substring(2);
			Object oneValue = valueMap.get(temp);
			if (oneValue == null)
				oneValue = valueMap.get(oneField);
			list.add(oneValue);
		}

		List<Object> valueList = new ArrayList<Object>();
		String sql = getQuerySql(model, fieldList, pageBean, likeFieldList);
		for (Object o : list) {
			if (o != null && !"".equals(o.toString())) {
				valueList.add(o);
			}
		}
		// valueList = removeNullValueFromList(valueList);

		return query(sql, null, valueList, model.getClass(), pageBean);
	}

	public Object queryByIdentity(Class entityClass, Long identity) {
		try {
			if (identity == null || identity == 0)
				return null;
			Class.forName(entityClass.getName());
			Object model = (entityClass.newInstance());
			setIdentityValue(model, identity);
			String sql = "select * from " + getTableName(entityClass) + " where " + getFieldPrefix() + getIdColumnNameByEntity(model) + "=?";
			List<Object> list = queryBySql(entityClass, sql, new Object[] { identity });
			return list != null && list.size() > 0 ? list.get(0) : null;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			if (log.isDebugEnabled())
				log.debug(e.getMessage());
			throw new RuntimeException(e);
		}
	}

	protected String getQuerySql(Object model, List<String> fieldList, PageBean pageBean, List<String> likeFieldList) {
		StringBuffer whereSql = new StringBuffer("");
		if (fieldList != null && fieldList.size() > 0) {
			whereSql.append(" where ");
			for (int i = 0; i < fieldList.size(); i++) {
				String f = fieldList.get(i);
				String temp = f;
				if (f.startsWith("f_")) {
					temp = f.substring(2, f.length());
				}
				if (!isFieldValueNull(model, temp)) {
					Object val = getFieldValue(model, temp);
					if (IS_SET_NULL_VALUE.equals(val)) {
						whereSql.append(f).append(" is null and ");
					} else {
						String logic = "=";
						if (likeFieldList.contains(f)) {
							logic = " like ";
						}
						whereSql.append(f).append(logic).append("? and ");
					}
				}
			}
			if (whereSql.toString().trim().endsWith("where")) {
				whereSql.delete(whereSql.length() - 6, whereSql.length());
			} else if (whereSql.length() > 0) {
				whereSql.delete(whereSql.length() - 4, whereSql.length());
			}
		}
		StringBuffer sql = new StringBuffer("select * from ").append(getTableName(model.getClass())).append(whereSql.toString());

		return sql.toString();
	}

	protected int getCountSqlIndex(int totalIndex, int tempIndex, String sql) {
		tempIndex = totalIndex;
		String temp = sql.substring(tempIndex);
		totalIndex += temp.indexOf("from") + 5;
		temp = sql.substring(tempIndex, totalIndex);
		if (temp.indexOf("(") != -1)
			totalIndex = getCountSqlIndex(totalIndex, tempIndex, sql);
		return totalIndex;
	}

	protected String getSetterName(String field) {
		String setter = "set" + field.substring(0, 1).toUpperCase() + field.substring(1);
		return setter;
	}

	protected String getGetterName(String field) {
		String getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
		return getter;
	}

	/**
	 * 判断一个Class的类型是否是基础类型。
	 * 
	 * @return
	 */
	protected boolean isBaseType(Class clazz) {
		if (Integer.class == clazz || Double.class == clazz || Float.class == clazz || Boolean.class == clazz || String.class == clazz || Long.class == clazz || Byte.class == clazz || Character.class == clazz || Date.class == clazz || Timestamp.class == clazz)
			return true;
		else
			return false;
	}

	protected List query(String sql, String countSql, List<Object> args, Class entityClass, PageBean pageBean) {
		if (pageBean != null) {
			if (countSql == null || "".equals(countSql.trim())) {
				countSql = getCountSqlBySql(sql);
			}
			Long countResult = queryCount(countSql, args.toArray());
			pageBean.setCountResult(countResult);

			long totalPage = 0;
			if (countResult % pageBean.getPageSize() == 0)
				totalPage = countResult / pageBean.getPageSize();
			else
				totalPage = countResult / pageBean.getPageSize() + 1;
			if (pageBean.getCurrentPage() > totalPage)
				return new ArrayList();
			pageBean.accountFirstResult();
			sql += " limit ?,?";
			args.add(pageBean.getFirstResult());
			args.add(pageBean.getPageSize());
			if (log.isDebugEnabled())
				log.debug("pageBean countResult:" + pageBean.getCountResult());
		}
		RowMapper<Object> rowMapper = disposeRowMapper(entityClass);
		List list = query(sql, args.toArray(), rowMapper);
		return list;
	}

	public long queryCount(String countSql, Object[] array) {
		return queryForObject(countSql, array, Long.class);
	}

	private String getCountSqlBySql(String sql) {
		int index = getCountSqlIndex(0, 0, sql);
		String tempCuntSql = sql.substring(index);
		return "select ifnull(count(*),0) from " + tempCuntSql;
	}

	public Object executeSql(String sql, Object[] param) {
		return update(sql, param);
	}

	public <T> T callable(CallableStatementCreator csc, CallableStatementCallback<T> action) {
		return execute(csc, action);
	}

	public DataSource getDatasource() {
		return this.getDataSource();
	}

	@Override
	public <T> T queryObjectBySql(Class<T> entityClass, String sql, Object[] args) {
		List<T> list = queryBySql(entityClass, sql, args);
		return list != null && list.size() > 0 ? list.get(0) : null;
	}
}
